const { exec } = require('child_process');
const fs = require('fs');
const path = require('path');

class BackupController {
  /**
   * Create a database backup
   */
  static async createBackup(req, res) {
    try {
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      const backupFileName = `financeapp_backup_${timestamp}.sql`;
      const backupDir = path.join(__dirname, '..', '..', 'backups');
      const backupPath = path.join(backupDir, backupFileName);
      
      // Ensure backup directory exists
      if (!fs.existsSync(backupDir)) {
        fs.mkdirSync(backupDir, { recursive: true });
      }
      
      // PostgreSQL connection details from environment variables
      const host = process.env.DB_HOST || 'localhost';
      const port = process.env.DB_PORT || '5432';
      const database = process.env.DB_NAME || 'financeapp';
      const username = process.env.DB_USER || 'financeapp_admin';
      
      // Create backup command
      const backupCommand = `pg_dump -h ${host} -p ${port} -U ${username} -d ${database} -f "${backupPath}"`;
      
      // Set environment variable for password
      const env = { ...process.env, PGPASSWORD: process.env.DB_PASSWORD };
      
      exec(backupCommand, { env }, (error, stdout, stderr) => {
        if (error) {
          console.error('Backup failed:', error);
          return res.status(500).json({ error: 'Backup failed', details: error.message });
        }
        
        if (stderr) {
          console.error('Backup stderr:', stderr);
          return res.status(500).json({ error: 'Backup failed', details: stderr });
        }
        
        res.json({
          message: 'Backup created successfully',
          backup_file: backupFileName,
          backup_path: backupPath
        });
      });
    } catch (error) {
      console.error('Create backup error:', error);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
  
  /**
   * List available backups
   */
  static async listBackups(req, res) {
    try {
      const backupDir = path.join(__dirname, '..', '..', 'backups');
      
      if (!fs.existsSync(backupDir)) {
        return res.json({ backups: [] });
      }
      
      const backups = fs.readdirSync(backupDir)
        .filter(file => file.endsWith('.sql'))
        .sort((a, b) => b.localeCompare(a)); // Sort by name (newest first)
      
      res.json({ backups });
    } catch (error) {
      console.error('List backups error:', error);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
  
  /**
   * Restore a database backup
   */
  static async restoreBackup(req, res) {
    try {
      const { backup_file } = req.body;
      
      if (!backup_file) {
        return res.status(400).json({ error: 'Backup file is required' });
      }
      
      const backupDir = path.join(__dirname, '..', '..', 'backups');
      const backupPath = path.join(backupDir, backup_file);
      
      // Check if backup file exists
      if (!fs.existsSync(backupPath)) {
        return res.status(404).json({ error: 'Backup file not found' });
      }
      
      // PostgreSQL connection details from environment variables
      const host = process.env.DB_HOST || 'localhost';
      const port = process.env.DB_PORT || '5432';
      const database = process.env.DB_NAME || 'financeapp';
      const username = process.env.DB_USER || 'financeapp_admin';
      
      // For safety, we won't automatically drop and recreate the database
      // Instead, we'll provide instructions to the user
      res.json({
        message: 'Backup file verified',
        backup_file: backup_file,
        instructions: [
          'To restore this backup, please follow these steps:',
          '1. Stop the application server',
          '2. Drop the current database: dropdb -h HOST -p PORT -U USERNAME DATABASE',
          '3. Create a new database: createdb -h HOST -p PORT -U USERNAME DATABASE',
          '4. Restore the backup: psql -h HOST -p PORT -U USERNAME -d DATABASE -f BACKUP_FILE',
          '5. Restart the application server'
        ],
        backup_path: backupPath,
        db_details: {
          host,
          port,
          database,
          username
        }
      });
    } catch (error) {
      console.error('Restore backup error:', error);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
  
  /**
   * Download a backup file
   */
  static async downloadBackup(req, res) {
    try {
      const { backup_file } = req.params;
      
      if (!backup_file) {
        return res.status(400).json({ error: 'Backup file is required' });
      }
      
      const backupDir = path.join(__dirname, '..', '..', 'backups');
      const backupPath = path.join(backupDir, backup_file);
      
      // Check if backup file exists
      if (!fs.existsSync(backupPath)) {
        return res.status(404).json({ error: 'Backup file not found' });
      }
      
      // Set headers for file download
      res.setHeader('Content-Disposition', `attachment; filename="${backup_file}"`);
      res.setHeader('Content-Type', 'application/sql');
      
      // Stream the file to the response
      const fileStream = fs.createReadStream(backupPath);
      fileStream.pipe(res);
      
      fileStream.on('error', (error) => {
        console.error('File stream error:', error);
        res.status(500).json({ error: 'Failed to download backup file' });
      });
    } catch (error) {
      console.error('Download backup error:', error);
      res.status(500).json({ error: 'Internal server error' });
    }
  }
}

module.exports = BackupController;